home *** CD-ROM | disk | FTP | other *** search
/ CD ROM Paradise Collection 4 / CD ROM Paradise Collection 4 1995 Nov.iso / program / swags_z.zip / SOUND.SWG / 0027_Lots of Sound.pas < prev    next >
Pascal/Delphi Source File  |  1993-08-27  |  20KB  |  742 lines

  1. {
  2. I've gotten tired of writing these routines and have gone on to other
  3. projects so I don't have time to work on them now.  I figured others may get
  4. some use out of them though.  They're not totally done yet, but what is there
  5. does work (as far as I can tell).  They support playing digitized Sound
  6. (signed or unsigned) at sample rates from 18hz to 44.1khz (at least on my
  7. 386sx/25), on the PC Speaker (polled), LPT DACs (1-4) or Adlib FM channels. I
  8. was planning on adding Sound Blaster DAC, Gravis UltraSound, and PC Speaker
  9. (pulse width modulated) support.  I also planned on adding VOC support.  I
  10. may add those at a later date, but no promises.  I'll release any new updates
  11. (if there are any) through the PDN since these routines are a little long
  12. (this will be the ONLY post of these routines in this echo).  I haven't
  13. tested the LPT DAC routines, so could someone who has an LPT DAC please test
  14. them and let me know if they work?  (They SHOULD work, but you never know.)
  15. These routines work For me under Turbo Pascal V6.0 on my 386sx/25.
  16. }
  17.  
  18. Unit Digital;
  19. (*************************************************************************)
  20. (*                                                                       *)
  21. (*  Programmed by David Dahl                                             *)
  22. (*  This Unit and all routines are PUBLIC DOMAIN.                        *)
  23. (*                                                                       *)
  24. (*  Special thanks to Emil Gilliam For information (and code!) on Adlib  *)
  25. (*  digital output.                                                      *)
  26. (*                                                                       *)
  27. (*  if you use any of these routines in your own Programs, I would       *)
  28. (*  appreciate an acknowledgement in the docs and/or Program... and I'm  *)
  29. (*  sure Mr. Gilliam wouldn't Object to having his name mentioned, too.  *)
  30. (*                                                                       *)
  31. (*************************************************************************)
  32. Interface
  33.  
  34. Const
  35.   BufSize       = 2048;
  36.  
  37. Type
  38.   BufferType = Array[1 .. BufSize] of Byte;
  39.   BufPointer = ^BufferType;
  40.  
  41.   DeviceType = (LPT1, LPT2, LPT3, LPT4, PcSpeaker, PCSpeakPW, Adlib,
  42.                 SoundBlaster, UltraSound);
  43.  
  44. Var
  45.   DonePlaying : Boolean;
  46.  
  47. Procedure SetOutPutDevice(DeviceName : DeviceType; SignedSamples : Boolean);
  48. Procedure SetPlaySpeed(Speed : LongInt);
  49.  
  50. Procedure PlayRAWSoundFile(FileName : String; SampleRate : Word);
  51. Function  LoadBuffer(Var F : File; Var BufP : BufPointer) : Word;
  52. Procedure PlayBuffer(BufPtr : BufPointer; Size : Word);
  53.  
  54. Procedure HaltPlaying;
  55. Procedure CleanUp;
  56.  
  57. Implementation
  58.  
  59. Uses
  60.   Crt;
  61.  
  62. Const
  63.   C8253ModeControl   = $43;
  64.   C8253Channel       : Array [0..2] of Byte = ($40, $41, $42);
  65.   C8253OperatingFreq = 1193180;
  66.   C8259Command       = $20;
  67.  
  68.   TimerInterrupt     = $08;
  69.   AdlibIndex         = $388;
  70.   AdlibReg           = $389;
  71.  
  72. Type
  73.   ZeroAndOne = 0..1;
  74.  
  75. Var
  76.   DataLength  : Word;
  77.   Buffer      : BufPointer;
  78.  
  79.   LPTAddress  : Word;
  80.   LPTPort     : Array [1 .. 4] of Word Absolute $0040 : $0008;
  81.  
  82.   OldTimerInterrupt : Pointer;
  83.   InterruptVector   : Array [0..255] of Pointer Absolute $0000 : $0000;
  84.  
  85. {=[ Misc Procedures ]=====================================================}
  86.  
  87. {-[ Clear Interrupt Flag (Disable Maskable Interrupts) ]------------------}
  88. Procedure CLI;
  89. Inline($FA);
  90.  
  91. {-[ Set Interrupt Flag ]--------------------------------------------------}
  92. Procedure STI;
  93. Inline($FB);
  94.  
  95.  
  96. {=[ Initialize Sound Devices ]============================================}
  97.  
  98. {-[ Initialize Adlib FM For Digital Output ]------------------------------}
  99. Procedure InitializeAdlib;
  100. Var
  101.   TempInt : Pointer;
  102.  
  103.   Procedure Adlib(Reg, Data : Byte); Assembler;
  104.   Asm
  105.     mov  dx, AdlibIndex            { Adlib index port }
  106.     mov  al, Reg
  107.  
  108.     out  dx,al                     { Set the index }
  109.  
  110.     { Wait For hardware to respond }
  111.     in al, dx; in al, dx; in al, dx
  112.     in al, dx; in al, dx; in al, dx
  113.  
  114.     inc  dx                        { Adlib register port }
  115.     mov  al, Data
  116.     out  dx, al                    { Set the register value }
  117.  
  118.     dec  dx                        { Adlib index port }
  119.  
  120.     { Wait For hardware to respond }
  121.     in al, dx; in al, dx; in al, dx; in al, dx; in al, dx
  122.     in al, dx; in al, dx; in al, dx; in al, dx; in al, dx
  123.     in al, dx; in al, dx; in al, dx; in al, dx; in al, dx
  124.     in al, dx; in al, dx; in al, dx; in al, dx; in al, dx
  125.     in al, dx; in al, dx; in al, dx; in al, dx; in al, dx
  126.     in al, dx; in al, dx; in al, dx; in al, dx; in al, dx
  127.     in al, dx; in al, dx; in al, dx; in al, dx; in al, dx
  128.  
  129.   end;
  130.  
  131. begin
  132.   Adlib($00, $00);    { Set Adlib test Register }
  133.   Adlib($20, $21);    { Operator 0: MULTI=1, AM=VIB=KSR=0, EG=1 }
  134.   Adlib($60, $F0);    { Attack = 15, Decay = 0 }
  135.   Adlib($80, $F0);    { Sustain = 15, Release = 0 }
  136.   Adlib($C0, $01);    { Feedback = 0, Additive Synthesis = 1 }
  137.   Adlib($E0, $00);    { Waveform = Sine Wave }
  138.   Adlib($43, $3F);    { Operator 4: Total Level = 63, Attenuation = 0 }
  139.   Adlib($B0, $01);    { Fnumber = 399 }
  140.   Adlib($A0, $8F);
  141.   Adlib($B0, $2E);    { FNumber = 143, Key-On }
  142.  
  143.   { Wait For the operator's sine wave to get to top and then stop it there
  144.     That way, we have an operator who's wave is stuck at the top, and we can
  145.     play digitized Sound by changing it's total level (volume) register. }
  146.  
  147.   Asm
  148.     mov  al, 0                    { Get timer 0 value into DX }
  149.     out  43h, al
  150.     jmp  @Delay1
  151.  
  152.    @Delay1:
  153.     in   al, 40h
  154.     mov  dl, al
  155.     jmp  @Delay2
  156.  
  157.    @Delay2:
  158.     in   al, 40h
  159.  
  160.     mov  dh, al
  161.     sub  dx, 952h                 { Target value }
  162.  
  163.    @wait_loop:
  164.     mov  al, 0                    { Get timer 0 value into BX }
  165.     out  43h, al
  166.     jmp  @Delay3
  167.  
  168.    @Delay3:
  169.     in   al, 40h
  170.     mov  bl, al
  171.     jmp  @Delay4
  172.  
  173.    @Delay4:
  174.     in   al, 40h
  175.     mov  bh, al
  176.     cmp  bx, dx                   { Have we waited that much time yet? }
  177.     ja   @wait_loop               { if no, then go back }
  178.  
  179.   end;
  180.  
  181.  { Now that the sine wave is at the top, change its frequency to 0 to keep
  182.    it from moving  }
  183.  
  184.   Adlib($B0, $20);  { F-Number = 0 }
  185.   Adlib($A0, $00);  { Frequency = 0 }
  186.  
  187.   Port[AdlibIndex] := $40;
  188. end;
  189.  
  190. {=[ Sound Device Handlers ]===============================================}
  191. Procedure PlayPCSpeaker; Interrupt;
  192. Const
  193.   Counter : Word = 1;
  194. begin
  195.   if Not(DonePlaying) Then
  196.   begin
  197.     if Counter <= DataLength Then
  198.     begin
  199.       Port[$61] := (Port[$61] and 253) OR ((Buffer^[Counter] and 128) SHR 6);
  200.       Inc(Counter);
  201.     end
  202.     else
  203.     begin
  204.       DonePlaying := True;
  205.       Counter     := 1;
  206.     end;
  207.   end;
  208.  
  209.   Port[C8259Command] := $20; { Enable Interrupts }
  210. end;
  211.  
  212. Procedure PlayPCSpeakerSigned; Interrupt;
  213. Const
  214.   Counter : Word = 1;
  215. begin
  216.   if Not(DonePlaying) Then
  217.   begin
  218.     if Counter <= DataLength Then
  219.     begin
  220.       Port[$61] := (Port[$61] and 253) OR
  221.                    ((Byte(shortint(Buffer^[Counter]) + 128) AND 128) SHR 6);
  222.       Inc(Counter);
  223.     end
  224.     else
  225.     begin
  226.       DonePlaying := True;
  227.       Counter     := 1;
  228.     end;
  229.   end;
  230.  
  231.   Port[C8259Command] := $20; { Enable Interrupts }
  232. end;
  233.  
  234. Procedure PlayLPT; Interrupt;
  235. Const
  236.   Counter : Word = 1;
  237. begin
  238.   if Not(DonePlaying) Then
  239.   begin
  240.     if Counter <= DataLength Then
  241.     begin
  242.       Port[LPTAddress] := Buffer^[Counter];
  243.       Inc(Counter);
  244.     end
  245.     else
  246.     begin
  247.       DonePlaying := True;
  248.       Counter     := 1;
  249.     end;
  250.   end;
  251.  
  252.   Port[C8259Command] := $20; { Enable Interupts }
  253. end;
  254.  
  255. Procedure PlayLPTSigned; Interrupt;
  256. Const
  257.   Counter : Word = 1;
  258. begin
  259.   if Not(DonePlaying) Then
  260.   begin
  261.     if Counter <= DataLength Then
  262.     begin
  263.       Port[LPTAddress] := Byte(shortint(Buffer^[Counter]) + 128);
  264.       Inc(Counter);
  265.     end
  266.     else
  267.     begin
  268.       DonePlaying := True;
  269.       Counter     := 1;
  270.     end;
  271.   end;
  272.  
  273.   Port[C8259Command] := $20; { Enable Interupts }
  274. end;
  275.  
  276. Procedure PlayAdlib; Interrupt;
  277. Const
  278.   Counter : Word = 1;
  279. begin
  280.   if Not(DonePlaying) Then
  281.   begin
  282.     if Counter <= DataLength Then
  283.     begin
  284.       Port[AdlibReg] := (Buffer^[Counter] SHR 2);
  285.       Inc(Counter);
  286.     end
  287.     else
  288.     begin
  289.       DonePlaying := True;
  290.       Counter     := 1;
  291.     end;
  292.   end;
  293.  
  294.   Port[C8259Command] := $20; { Enable Interupts }
  295. end;
  296.  
  297. Procedure PlayAdlibSigned; Interrupt;
  298. Const
  299.   Counter : Word = 1;
  300. begin
  301.   if Not(DonePlaying) Then
  302.   begin
  303.     if Counter <= DataLength Then
  304.     begin
  305.       Port[AdlibReg] := Byte(shortint(Buffer^[Counter]) + 128) SHR 2;
  306.       Inc(Counter);
  307.     end
  308.     else
  309.     begin
  310.       DonePlaying := True;
  311.       Counter     := 1;
  312.     end;
  313.   end;
  314.  
  315.   Port[C8259Command] := $20; { Enable Interupts }
  316. end;
  317.  
  318. {=[ 8253 Timer Programming Routines ]=====================================}
  319. Procedure Set8253Channel(ChannelNumber : Byte; ProgramValue : Word);
  320. begin
  321.   Port[C8253ModeControl] := 54 or (ChannelNumber SHL 6); { XX110110 }
  322.   Port[C8253Channel[ChannelNumber]] := Lo(ProgramValue);
  323.   Port[C8253Channel[ChannelNumber]] := Hi(ProgramValue);
  324. end;
  325.  
  326. {-[ Set Clock Channel 0 (INT 8, IRQ 0) To Input Speed ]-------------------}
  327. Procedure SetPlaySpeed(Speed : LongInt);
  328. Var
  329.   ProgramValue : Word;
  330. begin
  331.   ProgramValue := C8253OperatingFreq div Speed;
  332.   Set8253Channel(0, ProgramValue);
  333. end;
  334.  
  335. {-[ Set Clock Channel 0 Back To 18.2 Default Value ]----------------------}
  336. Procedure SetDefaultTimerSpeed;
  337. begin
  338.   Set8253Channel (0, 0);
  339. end;
  340.  
  341.  
  342. {=[ File Handling ]=======================================================}
  343.  
  344. {-[ Load Buffer With Data From Raw File ]---------------------------------}
  345. Function LoadBuffer(Var F : File; Var BufP : BufPointer) : Word;
  346. Var
  347.   NumRead : Word;
  348. begin
  349.   BlockRead(F, BufP^, BufSize, NumRead);
  350.   LoadBuffer := NumRead;
  351. end;
  352.  
  353.  
  354. {=[ Sound Playing / Setup Routines ]======================================}
  355.  
  356. {-[ Output Sound Data In Buffer ]-----------------------------------------}
  357. Procedure PlayBuffer(BufPtr : BufPointer; Size : Word);
  358. begin
  359.   Buffer      := BufPtr;
  360.   DataLength  := Size;
  361.   DonePlaying := False;
  362. end;
  363.  
  364. {-[ Halt Playing ]--------------------------------------------------------}
  365. Procedure HaltPlaying;
  366. begin
  367.   DonePlaying := True;
  368. end;
  369.  
  370. {=[ Initialize Data ]=====================================================}
  371. Procedure InitializeData;
  372. Const
  373.   CalledOnce : Boolean = False;
  374. begin
  375.   if Not(CalledOnce) Then
  376.   begin
  377.     DonePlaying       := True;
  378.     OldTimerInterrupt := InterruptVector[TimerInterrupt];
  379.     CalledOnce        := True;
  380.   end;
  381. end;
  382.  
  383. {=[ Set Interrupt Vectors ]===============================================}
  384.  
  385. {-[ Set Timer Interrupt Vector To Our Device ]----------------------------}
  386. Procedure SetOutPutDevice(DeviceName : DeviceType; SignedSamples : Boolean);
  387. begin
  388.   CLI;
  389.  
  390.   Case DeviceName of
  391.  
  392.     LPT1..LPT4 :
  393.       begin
  394.         LPTAddress := LPTPort[Ord(DeviceName)];
  395.         if SignedSamples Then
  396.           InterruptVector[TimerInterrupt] := @PlayLPTSigned
  397.         else
  398.           InterruptVector[TimerInterrupt] := @PlayLPT;
  399.       end;
  400.  
  401.     PCSpeaker :
  402.       if SignedSamples Then
  403.         InterruptVector[TimerInterrupt] := @PlayPCSpeakerSigned
  404.       else
  405.         InterruptVector[TimerInterrupt] := @PlayPCSpeaker;
  406.  
  407.     Adlib :
  408.       begin
  409.         InitializeAdlib;
  410.         if SignedSamples Then
  411.           InterruptVector[TimerInterrupt] := @PlayAdlibSigned
  412.         else
  413.           InterruptVector[TimerInterrupt] := @PlayAdlib;
  414.       end;
  415.  
  416.     else
  417.       begin
  418.         STI;
  419.  
  420.         Writeln;
  421.         Writeln ('That Sound Device Is Not Supported In This Version.');
  422.         Writeln ('Using PC Speaker In Polled Mode Instead.');
  423.  
  424.         CLI;
  425.         if SignedSamples Then
  426.           InterruptVector[TimerInterrupt] := @PlayPCSpeakerSigned
  427.         else
  428.           InterruptVector[TimerInterrupt] := @PlayPCSpeaker;
  429.       end;
  430.   end;
  431.   STI;
  432. end;
  433.  
  434. {-[ Set Timer Interupt Vector To Default Handler ]------------------------}
  435. Procedure SetTimerInterruptVectorDefault;
  436. begin
  437.   CLI;
  438.   InterruptVector[TimerInterrupt] := OldTimerInterrupt;
  439.   STI;
  440. end;
  441.  
  442. Procedure PlayRAWSoundFile(FileName : String; SampleRate : Word);
  443. Var
  444.   RawDataFile : File;
  445.   SoundBuffer : Array [ZeroAndOne] of BufPointer;
  446.   BufNum      : ZeroAndOne;
  447.   Size        : Word;
  448. begin
  449.   New(SoundBuffer[0]);
  450.   New(SoundBuffer[1]);
  451.  
  452.   SetPlaySpeed(SampleRate);
  453.  
  454.   Assign(RawDataFile, FileName);
  455.   Reset(RawDataFile, 1);
  456.  
  457.   BufNum := 0;
  458.   Size := LoadBuffer(RawDataFile, SoundBuffer[BufNum]);
  459.  
  460.   PlayBuffer(SoundBuffer[BufNum], Size);
  461.  
  462.   While Not(Eof(RawDataFile)) do
  463.   begin
  464.     BufNum := (BufNum + 1) and 1;
  465.     Size   := LoadBuffer(RawDataFile, SoundBuffer[BufNum]);
  466.  
  467.     Repeat Until DonePlaying;
  468.  
  469.     PlayBuffer(SoundBuffer[BufNum], Size);
  470.   end;
  471.  
  472.   Close (RawDataFile);
  473.  
  474.   Repeat Until DonePlaying;
  475.  
  476.   SetDefaultTimerSpeed;
  477.  
  478.   Dispose(SoundBuffer[1]);
  479.   Dispose(SoundBuffer[0]);
  480. end;
  481.  
  482. {=[ MUST CALL BEFORE ExitING Program!!! ]=================================}
  483. Procedure CleanUp;
  484. begin
  485.   SetDefaultTimerSpeed;
  486.   SetTimerInterruptVectorDefault;
  487. end;
  488.  
  489. {=[ Set Up ]==============================================================}
  490. begin
  491.   InitializeData;
  492.   NoSound;
  493. end.
  494.  
  495.  
  496.  
  497.  
  498.  
  499.  
  500.  
  501. Program RAWDigitalOutput;
  502.  
  503. (*************************************************************************)
  504. (*                                                                       *)
  505. (*  Programmed by David Dahl                                             *)
  506. (*  This Program and all routines are PUBLIC DOMAIN.                     *)
  507. (*                                                                       *)
  508. (*  if you use any of these routines in your own Programs, I would       *)
  509. (*  appreciate an acknowledgement in the docs and/or Program.            *)
  510. (*                                                                       *)
  511. (*************************************************************************)
  512.  
  513. Uses
  514.   Crt,
  515.   Digital;
  516.  
  517. Type
  518.   String4  = String[4];
  519.   String35 = String[35];
  520.  
  521. Const
  522.   MaxDevices = 9;
  523.  
  524.   DeviceCommand  : Array [1..MaxDevices] of String4 =
  525.     ('-L1', '-L2', '-L3', '-L4',
  526.      '-P' , '-PM', '-A' , '-SB', '-GUS' );
  527.  
  528.   DeviceName : Array [1..MaxDevices] of String35 =
  529.     ('LPT DAC on LPT1',
  530.      'LPT DAC on LPT2',
  531.      'LPT DAC on LPT3',
  532.      'LPT DAC on LPT4',
  533.      'PC Speaker (Polled Mode)',
  534.      'PC Speaker (Pulse Width Modulated)',
  535.      'Adlib / SoundBlaster FM',
  536.      'SoundBlaster DAC',
  537.      'Gravis UltraSound');
  538.  
  539.   SignedUnsigned  : Array [False .. True] of String35 =
  540.     ('Unsigned Sample', 'Signed Sample');
  541.  
  542.  
  543. {-[ Return An All Capaitalized String ]-----------------------------------}
  544. Function UpString(StringIn : String) : String;
  545. Var
  546.   TempString : String;
  547.   Counter    : Byte;
  548. begin
  549.   TempString := '';
  550.   For Counter := 1 to Length (StringIn) do
  551.     TempString := TempString + UpCase(StringIn[Counter]);
  552.  
  553.   UpString := TempString;
  554. end;
  555.  
  556. {-[ Check if File Exists ]------------------------------------------------}
  557. Function FileExists(FileName : String) : Boolean;
  558. Var
  559.   F : File;
  560. begin
  561.   {$I-}
  562.   Assign (F, FileName);
  563.   Reset(F);
  564.   Close(F);
  565.   {$I+}
  566.   FileExists := (IOResult = 0) And (FileName <> '');
  567. end;
  568.  
  569. {=[ Comand Line Parameter Decode ]========================================}
  570. Function FindOutPutDevice : DeviceType;
  571. Var
  572.   Counter       : Byte;
  573.   DeviceCounter : Byte;
  574.   Found         : Boolean;
  575.   Device        : DeviceType;
  576. begin
  577.   Counter := 1;
  578.   Found   := False;
  579.   Device  := PcSpeaker;
  580.  
  581.   While (Counter <= ParamCount) and Not(Found) do
  582.   begin
  583.     For DeviceCounter := 1 To MaxDevices do
  584.       if UpString(ParamStr(Counter)) = DeviceCommand[DeviceCounter] Then
  585.       begin
  586.         Device := DeviceType(DeviceCounter - 1);
  587.         Found  := True;
  588.       end;
  589.  
  590.     Inc(Counter);
  591.   end;
  592.  
  593.   FindOutPutDevice := Device;
  594. end;
  595.  
  596. Function FindRawFileName : String;
  597. Var
  598.   FileNameFound : String;
  599.   TempName      : String;
  600.   Found         : Boolean;
  601.   Counter       : Byte;
  602. begin
  603.   FileNameFound   := '';
  604.   Counter := 1;
  605.   Found   := False;
  606.  
  607.   While (Counter <= ParamCount) and Not(Found) do
  608.   begin
  609.     TempName := UpString(ParamStr(Counter));
  610.     if TempName[1] <> '-' Then
  611.     begin
  612.       FileNameFound := TempName;
  613.       Found         := True;
  614.     end;
  615.     Inc (Counter);
  616.   end;
  617.  
  618.   FindRawFileName := FileNameFound;
  619. end;
  620.  
  621. Function FindPlayBackRate : Word;
  622. Var
  623.   RateString : String;
  624.   Rate       : Word;
  625.   Found      : Boolean;
  626.   Counter    : Byte;
  627.   ErrorCode  : Integer;
  628. begin
  629.   Rate := 22000;
  630.   Counter := 1;
  631.   Found   := False;
  632.  
  633.   While (Counter <= ParamCount) and Not(Found) do
  634.   begin
  635.     RateString := UpString(ParamStr(Counter));
  636.     if Copy(RateString,1,2) = '-F' Then
  637.     begin
  638.       RateString := Copy(RateString, 3, Length(RateString) - 2);
  639.       Val(RateString, Rate, ErrorCode);
  640.       if ErrorCode <> 0 Then
  641.       begin
  642.         Rate := 22000;
  643.         Writeln ('Error In Frequency. Using Default');
  644.       end;
  645.       Found := True;
  646.     end;
  647.     Inc (Counter);
  648.   end;
  649.  
  650.   if Rate < 18 Then
  651.     Rate := 18
  652.   else
  653.   if Rate > 44100 Then
  654.     Rate := 44100;
  655.  
  656.   FindPlayBackRate := Rate;
  657. end;
  658.  
  659. Function SignedSample : Boolean;
  660. Var
  661.   Found   : Boolean;
  662.   Counter : Word;
  663. begin
  664.   SignedSample := False;
  665.   Found   := False;
  666.   Counter := 1;
  667.  
  668.   While (Counter <= ParamCount) and Not(Found) do
  669.   begin
  670.     if UpString(ParamStr(Counter)) = '-S' Then
  671.     begin
  672.       SignedSample := True;
  673.       Found        := True;
  674.     end;
  675.  
  676.     Inc(Counter);
  677.   end;
  678. end;
  679.  
  680. {=[ Main Program ]========================================================}
  681. Var
  682.   SampleName : String;
  683.   SampleRate : Word;
  684.   OutDevice  : DeviceType;
  685. begin
  686.   Writeln;
  687.   Writeln('RAW Sound File Player V0.07');
  688.   Writeln('Programmed By David Dahl');
  689.   Writeln('Thanks to Emil Gilliam For Adlib digital output information');
  690.   Writeln('This Program is PUBLIC DOMAIN');
  691.  
  692.   if ParamCount <> 0 Then
  693.   begin
  694.     SampleRate := FindPlayBackRate;
  695.     SampleName := FindRawFileName;
  696.     OutDevice  := FindOutPutDevice;
  697.     Writeln;
  698.  
  699.     if SampleName <> '' Then
  700.     begin
  701.       Writeln('Raw File   : ',SampleName);
  702.       Writeln('Format     : ',SignedUnsigned[SignedSample]);
  703.       Writeln('Sample Rate: ',SampleRate);
  704.       Writeln('Device     : ',DeviceName[Ord(OutDevice)+1]);
  705.  
  706.       if FileExists(SampleName) Then
  707.       begin
  708.         SetOutputDevice(OutDevice, SignedSample);
  709.         PlayRAWSoundFile(SampleName, SampleRate);
  710.       end
  711.       else
  712.         Writeln('Sound File Not Found.');
  713.     end
  714.     else
  715.       Writeln('Filename Not Specified.');
  716.   end
  717.   else
  718.   begin
  719.     Writeln;
  720.     Writeln('USAGE:');
  721.     Writeln(ParamStr(0),' [SWITCHES] <RAW DATA File>');
  722.     Writeln;
  723.     Writeln('SWITCHES:');
  724.     Writeln(' -P      PC Speaker, Polled (Default)');
  725.     Writeln(' -L1     LPT DAC on LPT 1');
  726.     Writeln(' -L2     LPT DAC on LPT 2');
  727.     Writeln(' -L3     LPT DAC on LPT 3');
  728.     Writeln(' -L4     LPT DAC on LPT 4');
  729.     Writeln(' -A      Adlib/Sound Blaster FM');
  730.     Writeln;
  731.     Writeln(' -S      Signed Sample (Unsigned Default)');
  732.     Writeln;
  733.     Writeln(' -FXXXXX Frequency Of Sample. XXXXX can be any Integer ',
  734.              'between 18 to 44100');
  735.     Writeln ('         (22000 Default)');
  736.   end;
  737.  
  738.   CleanUp;
  739. end.
  740.  
  741.  
  742.